// 类的介绍
// class Greeter {
//   greeting: string
//   constructor(message: string) {
//     this.greeting = message
//   }
//   greet() {
//     return `Hello, ${this.greeting}`
//   }
// }

// let greeter = new Greeter('World')
// console.log(greeter)
// console.log(greeter.greet())


// 继承
// class Animal {
//   move (distanceInMeters: number = 0) {
//     console.log(`Animal moved ${distanceInMeters}m.`)
//   }
// }

// class Dog extends Animal {
//   back() {
//     console.log('Woof! Woof!')
//   }
// }

// const dog = new Dog()
// dog.move(100)
// dog.back()

// 复杂的继承例子
// class Animal {
//   name: string
//   constructor(theName: string) { this.name = theName }
//   move(distanceInMeters: number = 0) {
//     console.log(`${this.name} moved ${distanceInMeters}m.`)
//   }
// }

// class Snake extends Animal {
//   constructor(name: string) { super(name) }
//   move(distanceInMeters = 5) {
//     console.log('Slithering...')
//     super.move(distanceInMeters)
//   }
// }

// class Horse extends Animal {
//   constructor(name: string) { super(name) }
//   move(distanceInMeters = 45) {
//     console.log('Galloping...')
//     super.move(distanceInMeters)
//   }
// }

// let sam = new Snake('Sammy the Python')
// let tom: Animal = new Horse('Tommt the Palomino')

// sam.move()
// tom.move(34)


// 修饰符，默认为 public
// class Animal {
//   public name: string
//   public constructor(theName: string) { this.name = theName }
//   public move(distanceInMeters: number) {
//     console.log(`${this.name} moved ${distanceInMeters}m.`)
//   }
// }

// private
// class Animal {
//   private name: string
//   public constructor(theName: string) { this.name = theName }
//   public move(distanceInMeters: number) {
//     console.log(`${this.name} moved ${distanceInMeters}m.`)
//   }
// }

// new Animal('Cat').name // 报错，属性“name”为私有属性，只能在类“Animal”中访问

// 类型兼容
// class Animal {
//   private name: string
//   constructor(theName: string) { this.name = theName }
// }

// class Rhino extends Animal {
//   constructor() {super('Rhino')}
// }

// class Employee {
//   private name: string
//   constructor(theName: string) { this.name = theName }
// }

// let animal = new Animal('Goat')
// let rhino = new Rhino()
// let employee = new Employee('Bob')
// animal = rhino
// animal = employee // 报错


// protected
// class Person {
//   protected name: string
//   constructor(name: string) { this.name = name }
// }

// class Employee extends Person {
//   private department: string
//   constructor(name: string, department: string) {
//     super(name)
//     this.department = department
//   }

//   public getElevatorPitch() {
//     return `Hello, my name is ${this.name} and I work in ${this.department}`
//   }
// }

// let howard = new Employee('Howard', 'Sales')
// console.log(howard.getElevatorPitch())
// console.log(howard.name) // 报错，属性“name”受保护，只能在类“Person”及其子类中访问。

// 构造函数被标记为 protected
// class Person {
//   protected name: string
//   protected constructor(theName: string) { this.name = theName }
// }

// // Employee 能够继承 Person
// class Employee extends Person {
//   private department: string
//   constructor(name: string, department: string) {
//     super(name)
//     this.department = department
//   }
//   public getElevatorPitch() {
//     return `Hello, my name is ${this.name} and I work in ${this.department}`
//   }
// }

// let howard = new Employee('Howard', 'Sales')
// let john = new Person('John') // 报错，类“Person”的构造函数是受保护的，仅可在类声明中访问。

// readonly 修饰符
// class Octopus {
//   readonly name: string
//   readonly numberOfLegs: number = 8
//   constructor(theName: string) {
//     this.name = theName
//   }
// }

// let dad = new Octopus('haha')
// dad.name = 'eeee' // 报错，无法分配到 "name" ，因为它是只读属性。

// 参数属性（重写上述类）
// class Octopus {
//   readonly numberOfLegs: number = 8
//   constructor(readonly name: string) {}
// }


// 存取器
// 没有使用存取器
// class Employee {
//   fullName: string
// }

// let employee = new Employee()
// employee.fullName = 'Bob'
// if (employee.fullName) {
//   console.log(employee.fullName)
// }

// 使用存取器
// let passcode = 'secret passcode'

// class Employee {
//   private _fullName: string
  
//   get fullName(): string {
//     return this._fullName
//   }

//   set fullName(newName: string) {
//     if (passcode && passcode === 'secret passcode') {
//       this._fullName = newName
//     } else {
//       console.log('Error:Unauthorized')
//     }
//   }
// }

// let employee = new Employee()
// employee.fullName = 'Bob'
// if (employee.fullName) {
//   console.log(employee.fullName)
// }

// 静态属性
// class Grid {
//   static origin = { x: 0, y: 0 }
//   calculateDistanceFromOrigin(point: { x: number, y: number }) {
//     let xDist = (point.x - Grid.origin.x)
//     let yDist = (point.y - Grid.origin.y)
//     return (xDist * xDist + yDist * yDist) / this.scale
//   }
//   constructor(public scale: number) {}
// }

// let grid1 = new Grid(1.0)
// let grid2 = new Grid(5.0)

// console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 }))
// console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 }))


// 抽象类
// abstract class Animal {
//   abstract makeSound(): void
//   move(): void {
//     console.log('roaming this earth ...')
//   }
// }

// abstract class Department {
//   constructor(public name: string) {}

//   printName(): void {
//     console.log('Department name:' + this.name)
//   }

//   abstract printMeeting(): void // 必须在派生类中实现
// }

// class AccountingDepartment extends Department {
//   constructor() {
//     super('Accounting and Auditing') // 在派生类的构造函数中必须调用 super()
//   }

//   printMeeting(): void {
//     console.log('The Accounting Department')
//   }

//   generateReports(): void {
//     console.log('Generating accounting reports...')
//   }
// }

// let department: Department // 允许创建一个对抽象类型的引用
// department = new Department() // 错误，不能创建一个抽象类的实例
// department = new AccountingDepartment() // 允许对一个抽象子类进行实例化和赋值
// department.printName()
// department.printMeeting()
// department.generateReports() // 错误，类型“Department”上不存在属性“generateReports”


// 把类当做接口使用
class Point {
  x: number
  y: number
}

interface Point3d extends Point {
  z: number
}

let point3d: Point3d = { x: 1, y: 2, z: 3 }
console.log(point3d)